﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace ConstantCMapEditor3
{
    public class LightSourceComponent : Declaration
    {
        TextSprite spriteTxt;

        //讀取資源與命名
        public LightSourceComponent()
        {
            sprite = new Sprite(IntelligentTexture.IntelligentLoad("lightSource"));
            sprite.UserData = this;
            spriteTxt = new TextSprite();
            sprite.SpriteColor = new Color(100, 100, 100, 100);

            light = new LightSourceScene();

            sprite.AttachChild(light);

            Size = new Vector2(200, 200);

        }

        LightSourceScene light;


        override public void InstanceInit()
        {
            LightSourceComponent box = new LightSourceComponent();
            box.InstanceReal(this);
        }

        private void InstanceReal(LightSourceComponent Candidate)
        {
            sprite.TouchEvent += MouseEvent;
            spriteTxt.Text = "Selected: ";
            spriteTxt.Text += ClassID = "obj" + DateTime.Now.Second + DateTime.Now.Millisecond + Game1.declarationList.Count;
            spriteTxt.Position = new Vector2(spriteTxt.Width / 2 + 50, spriteTxt.Height / 2 + 200);
            spriteTxt.SpriteColor = Color.Green;
            Game1.lineHolderList.Add(this);
            Game1.declarationList.Add(this);
            Game1.MapEditorScene.AttachChild(sprite);
            sprite.Touchable = true;

             DeclarationDeocrator.ChangeRenameButton(spriteTxt, this, 0, 230);
             DeclarationDeocrator.ChangeColorButton(spriteTxt, light, 0, 200);
             DeclarationDeocrator.SetLightChangeButton(spriteTxt, this, 0, 260);

            spriteTxt.Touchable = true;

            RangeModifierType = Candidate.RangeModifierType;
            RangeBase = Candidate.RangeBase;
            RangeDif = Candidate.RangeDif;
            RangeTime = Candidate.RangeTime;
            lightType = Candidate.lightType;
            Shadow = Candidate.Shadow;

            IntensityModifierType = Candidate.IntensityModifierType;
            IntensityBase = Candidate.IntensityBase;
            IntensityDif = Candidate.IntensityDif;
            IntensityTime = Candidate.IntensityTime;

            ModifierReset();
        }

        private void Delete()
        {
            Game1.lineHolderList.Remove(this);
            Game1.declarationList.Remove(this);
            Game1.MapEditorScene.DettachChild(sprite);
            Game1.Selected = null;
        }

        public int Shadow
        {
            get
            {
                return light.Shadow;
            }
            set
            {
                light.Shadow = value;
            }
        }


        override public void CandidateInit()
        {
            Position = new Vector2(sprite.Width / 2 + 50, sprite.Height / 2 + 50);

            spriteTxt.Text = ClassID = "LightSourceComponent";
            spriteTxt.Position = new Vector2(spriteTxt.Width / 2 + 0, spriteTxt.Height / 2 + 0);
            spriteTxt.SpriteColor = Color.Green;

            sprite.Touchable = false;
        }

        public int lightType 
        {
            get 
            {
                return light.LightType;

            }
            set 
            {
                light.LightType = value;
            }
        }

        //產生後被點到
        private void MouseEvent(MouseEvent mouseEvent, Scene sender)
        {
            if (mouseEvent.ClickDownEdgeL) Game1.Selected = this;
            if (mouseEvent.PressedL)
            {
                Position += mouseEvent.Position - mouseEvent.PrePosition;
            }

            if (mouseEvent.PressedM)
            {
                Game1.CoordinateScene.Position += mouseEvent.Position - mouseEvent.PrePosition;
            }

            if (mouseEvent.WheelDown) 
            {
                light.LightType++;
            }

            if (mouseEvent.WheelUp)
            {
                light.LightType--;
            }

            if (KeyBoardManager.IsKeyEdgeDown(Keys.PageUp) && Game1.CoordinateScene.Scale > 0.5f) Game1.CoordinateScene.Scale -= 0.1f;
            if (KeyBoardManager.IsKeyEdgeDown(Keys.PageDown)) Game1.CoordinateScene.Scale += 0.1f;
            if (KeyBoardManager.IsKeyEdgeDown(Keys.Home)) Game1.CoordinateScene.Scale = 1.0f;

            if (mouseEvent.ClickDownEdgeR && Keyboard.GetState().IsKeyDown(Keys.LeftControl) && Game1.Selected != null)
            {
                Vector2 dis = Position - Game1.Selected.Position;
                Vector2 abs = new Vector2(Math.Abs(dis.X), Math.Abs(dis.Y));

                if (abs.X > abs.Y)
                {
                    Vector2 temp = Game1.Selected.Position;
                    temp.Y = Position.Y;

                    float selfWidth = Size.X;

                    if (RotateR > 1.5 && RotateR < 2) selfWidth = Size.Y;
                    if (RotateR > 1.5 + 3.14 && RotateR < 2 + 3.14) selfWidth = Size.Y;

                    if (temp.X > Position.X)
                        temp.X = Position.X + selfWidth;
                    else
                        temp.X = Position.X - selfWidth;

                    Game1.Selected.Position = temp;
                }
                else
                {
                    Vector2 temp = Game1.Selected.Position;
                    temp.X = Position.X;

                    float selfWidth = Size.Y;

                    if (RotateR > 1.5 && RotateR < 2) selfWidth = Size.X;
                    if (RotateR > 1.5 + 3.14 && RotateR < 2 + 3.14) selfWidth = Size.X;


                    if (temp.Y > Position.Y)
                        temp.Y = Position.Y + selfWidth;
                    else
                        temp.Y = Position.Y - selfWidth;

                    Game1.Selected.Position = temp;
                }
            }
        }

        override public bool ReadBack(String str)
        {
            if (str.Contains("LightSourceScene"))
            {
                InstanceInit();
                LightSourceComponent box = (LightSourceComponent)Game1.declarationList[Game1.declarationList.Count - 1];
                //Get Property

                String[] temp;
                temp = str.Split(", )".ToCharArray());

                for (int i = 0; i < temp.Length; i++) 
                {
                    Console.WriteLine(i + "." + temp[i]);
                }

                    box.ClassID = temp[1];

                int X = Convert.ToInt32(temp[5]);
                int Y = Convert.ToInt32(temp[7]);
                int W = Convert.ToInt32(temp[9]);
                int H = Convert.ToInt32(temp[11]);
                double R = Convert.ToDouble(temp[13].Replace('f', ' '));

                box.Size = new Vector2(W, H);
                box.Position = new Vector2(X, Y);
                box.RotateR = (float)R;

                int CR = Convert.ToInt32(temp[17]);
                int CG = Convert.ToInt32(temp[19]);
                int CB = Convert.ToInt32(temp[21]);
                double intensity = Convert.ToDouble(temp[23].Replace('f', ' '));

                box.color = new Color(CR,CG,CB);
                box.Intensity = (float)intensity;

                int lightType = Convert.ToInt32(temp[25]);
                box.light.LightType = lightType;

                try
                {
                    box.Shadow = Convert.ToInt32(temp[27]);
                }
                catch 
                {
                }

                try
                {
                    if (temp[29].Contains("None")) 
                    {
                        box.RangeModifierType = ModifierType.None;
                    }
                    else if (temp[29].Contains("Sin"))
                    {
                        box.RangeModifierType = ModifierType.Sin;
                    }
                    else if (temp[29].Contains("Cos"))
                    {
                        box.RangeModifierType = ModifierType.Cos;
                    }
                    else if (temp[29].Contains("Linear"))
                    {
                        box.RangeModifierType = ModifierType.Linear;
                    }

                    box.RangeBase = (float)Convert.ToDouble(temp[31].Replace('f', ' '));

                    box.RangeDif = (float)Convert.ToDouble(temp[33].Replace('f', ' '));

                    box.RangeTime = (float)Convert.ToDouble(temp[35].Replace('f', ' '));

                    if (temp[37].Contains("None"))
                    {
                        box.IntensityModifierType = ModifierType.None;
                    }
                    else if (temp[37].Contains("Sin"))
                    {
                        box.IntensityModifierType = ModifierType.Sin;
                    }
                    else if (temp[37].Contains("Cos"))
                    {
                        box.IntensityModifierType = ModifierType.Cos;
                    }
                    else if (temp[37].Contains("Linear"))
                    {
                        box.IntensityModifierType = ModifierType.Linear;
                    }

                    box.IntensityBase = (float)Convert.ToDouble(temp[39].Replace('f', ' '));

                    box.IntensityDif = (float)Convert.ToDouble(temp[41].Replace('f', ' '));

                    box.IntensityTime = (float)Convert.ToDouble(temp[43].Replace('f', ' '));
                }
                catch 
                {
                    RangeModifierType = ModifierType.None;
                   IntensityModifierType = ModifierType.None;
                }

                box.ModifierReset();

                return true;
            };
            return false;
        }

        //PhysicalFactory.CreateMidBox(this, 393, 410, 0f);
        override public String SaveOut()
        {
            return "LightSourceScene " + ClassID + " = PhysicalFactory.CreateLightSourceScene(this, " + (int)Position.X + ", " + 
                (int)Position.Y + ", " + (int)Size.X + ", " + (int)Size.Y + ", " + RotateR + "f, \"" + ClassID + "\", " + 
                light.SpriteColor.R + ", " + light.SpriteColor.G + ", " + light.SpriteColor.B + ", " + light.Intensity + "f, " + 
                light.LightType + ", " + light.Shadow.ToString().ToLower() + ", ModifierType." + this.RangeModifierType + ", " +
                RangeBase + "f, " + RangeDif + "f, " + RangeTime + "f, ModifierType." + this.IntensityModifierType + ", " + 
                IntensityBase + "f, " + IntensityDif + "f, " + IntensityTime + "f);";
        }

        public float Intensity 
        {
            get 
            {
                return light.Intensity;
            }
            set 
            {
                light.Intensity = value;
            }
        }

        override public void SelectedAction()
        {
            Game1.MapEditorUIScene.AttachChild(spriteTxt);
        }

        override public void SelectedUpdate()
        {
            if (Keyboard.GetState().IsKeyDown(Keys.Right)) Position += new Vector2(1, 0);
            if (Keyboard.GetState().IsKeyDown(Keys.Left)) Position -= new Vector2(1, 0);
            if (Keyboard.GetState().IsKeyDown(Keys.Up)) Position -= new Vector2(0, 1);
            if (Keyboard.GetState().IsKeyDown(Keys.Down)) Position += new Vector2(0, 1);
            if (Keyboard.GetState().IsKeyDown(Keys.Q)) RotateR -= 0.01f;
            if (Keyboard.GetState().IsKeyDown(Keys.E)) RotateR += 0.01f;
            if (KeyBoardManager.IsKeyEdgeDown(Keys.Delete)) Delete();

            if (!Keyboard.GetState().IsKeyDown(Keys.LeftControl))
            {
                if (RangeModifierType == ModifierType.None)
                {
                    if (Keyboard.GetState().IsKeyDown(Keys.D)) Size += new Vector2(6, 0);
                    if (Keyboard.GetState().IsKeyDown(Keys.A)) Size -= new Vector2(6, 0);
                }
                else 
                {
                    if (Keyboard.GetState().IsKeyDown(Keys.D)) RangeBase += 6;
                    if (Keyboard.GetState().IsKeyDown(Keys.A)) RangeBase -= 6;
                }

                if (IntensityModifierType == ModifierType.None)
                {
                    if (Keyboard.GetState().IsKeyDown(Keys.W)) Intensity += 0.03f;
                    if (Keyboard.GetState().IsKeyDown(Keys.S)) Intensity -= 0.03f;
                }
                else
                {
                    if (Keyboard.GetState().IsKeyDown(Keys.D)) IntensityBase += 0.03f;
                    if (Keyboard.GetState().IsKeyDown(Keys.A)) IntensityBase -= 0.03f;
                }


            }
            else
            {
                if (RangeModifierType == ModifierType.None)
                {
                    if (Keyboard.GetState().IsKeyDown(Keys.D)) Size += new Vector2(2, 0);
                    if (Keyboard.GetState().IsKeyDown(Keys.A)) Size -= new Vector2(2, 0);
                }
                else
                {
                    if (Keyboard.GetState().IsKeyDown(Keys.D)) RangeBase += 2;
                    if (Keyboard.GetState().IsKeyDown(Keys.A)) RangeBase -= 2;
                }

                if (IntensityModifierType == ModifierType.None)
                {
                    if (Keyboard.GetState().IsKeyDown(Keys.W)) Intensity += 0.01f;
                    if (Keyboard.GetState().IsKeyDown(Keys.S)) Intensity -= 0.01f;
                }
                else
                {
                    if (Keyboard.GetState().IsKeyDown(Keys.D)) IntensityBase += 0.01f;
                    if (Keyboard.GetState().IsKeyDown(Keys.A)) IntensityBase -= 0.01f;
                }
            }

            if (Keyboard.GetState().IsKeyDown(Keys.Q)) RotateR -= 0.01f;
            if (Keyboard.GetState().IsKeyDown(Keys.E)) RotateR += 0.01f;

            if (Size.X < 10) Size = new Vector2(10, Size.Y);
            if (Size.Y < 10) Size = new Vector2(Size.X, 10);

            spriteTxt.Text = "Selected: ";
            spriteTxt.Text += ClassID;
            spriteTxt.Text += "\n Position =" + Position.ToString();
            spriteTxt.Text += "\n Range =" + Size.X.ToString();
            spriteTxt.Text += "\n Rotate =" + RotateR.ToString();
            spriteTxt.Text += "\n Intensity =" + light.Intensity.ToString();
            //spriteTxt.Text += "\n Shadow Type =" + light.Intensity.ToString();

            String ShadowType = "";
            if ((Shadow & Krypton.Lights.Light2D.SHADOW_TYPE_OBJECT)!=0) ShadowType += "O,";
            if ((Shadow & Krypton.Lights.Light2D.SHADOW_TYPE_WALL) != 0) ShadowType += "W,";
            if ((Shadow & Krypton.Lights.Light2D.SHADOW_TYPE_BLOCKER) != 0) ShadowType += "B,";

            spriteTxt.Text += "\n Shadow Type =" + ShadowType;

            spriteTxt.Position = new Vector2(spriteTxt.Width / 2, spriteTxt.Height / 2 + 200);
        }

        override public void UnSelectedAction()
        {
            Game1.MapEditorUIScene.DettachChild(spriteTxt);
        }
        //UI

        override public void UISelectedAction()
        {
            Game1.MapEditorUIScene.AttachChild(sprite);
            Game1.MapEditorUIScene.AttachChild(spriteTxt);
        }

        override public void UISelectedUpdate()
        {
        }

        override public void UnUISelectedAction()
        {
            Game1.MapEditorUIScene.DettachChild(sprite);
            Game1.MapEditorUIScene.DettachChild(spriteTxt);
        }

        //UI
        
        public Color color
        {
            get 
            {
                return light.SpriteColor;
            }
            set 
            {
                light.SpriteColor = value;
            }

        }


        override public Vector2 Position
        {
            get
            {
                return sprite.Position;
            }
            set
            {
                sprite.Position = value;
            }
        }

        override public Vector2 Size
        {
            get
            {
                return new Vector2(light.Width,light.Height);
            }
            set
            {
                light.Width = value.X;
                light.Height = value.Y;
            }
        }

        override public float RotateR
        {
            get
            {
                return sprite.Rotate;
            }
            set
            {
                sprite.Rotate = value;
            }
        }

        public enum ModifierType 
        {
            Linear,
            Sin,
            Cos,
            None,
        }

        public ModifierType RangeModifierType = ModifierType.None;
        public float RangeBase = 200;
        public float RangeDif = 100;
        public float RangeTime = 1000;

        public ModifierType IntensityModifierType = ModifierType.None;
        public float IntensityBase = 1;
        public float IntensityDif = 0.2f;
        public float IntensityTime = 1000;

        public void ModifierReset()
        {
            this.light.UnregisterModifier();

            if (RangeModifierType == ModifierType.None && IntensityModifierType == ModifierType.None) return;


            if (RangeModifierType != ModifierType.None) 
            {
                RangeModifier range = new RangeModifier(0, 1, Rangefunction, 0, RangeTime);
                light.RegisterModifier(new LoopModifier(range,-1));
            }

            if (IntensityModifierType != ModifierType.None)
            {
                IntensityModifier intensity = new IntensityModifier(0, 1, Intensityfunction, 0, IntensityTime);
                light.RegisterModifier(new LoopModifier(intensity,-1));
            }

        }

        public double Rangefunction(double Value)
        {
            
            if (RangeModifierType == ModifierType.Linear)
            {
                if (Value < 0.5f)
                {
                    return RangeBase + (RangeDif * Value * 2) - (RangeDif / 2.0f);
                }
                else 
                {
                    return RangeBase + (RangeDif * (1.0f-Value) * 2) - (RangeDif / 2.0f);
                }
            }
            else if (RangeModifierType == ModifierType.Sin)
            {
                return RangeBase + (RangeDif/2) * (Math.Sin(Value*Math.PI*2));
            }
            else if (RangeModifierType == ModifierType.Cos)
            {
                return RangeBase + (RangeDif / 2) * (Math.Cos(Value * Math.PI * 2));
            }

            return RangeBase;
        }

        public double Intensityfunction(double Value) 
        {
            if (IntensityModifierType == ModifierType.Linear)
            {
                if (Value < 0.5f)
                {
                    return IntensityBase + (IntensityDif * Value * 2) - (IntensityDif / 2.0f);
                }
                else
                {
                    return IntensityBase + (IntensityDif * (1.0f - Value) * 2) - (IntensityDif / 2.0f);
                }
            }
            else if (IntensityModifierType == ModifierType.Sin)
            {
                return IntensityBase + (IntensityDif / 2) * (Math.Sin(Value * Math.PI * 2));
            }
            else if (IntensityModifierType == ModifierType.Cos)
            {
                return IntensityBase + (IntensityDif / 2) * (Math.Cos(Value * Math.PI * 2));
            }

            return IntensityBase;
        }


    }
}
